home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Guided Tour of Multimedia (Second Edition)
/
The Guided Tour of Multimedia (Second Edition).iso
/
trials
/
director
/
evalcopy
/
director.z
/
MECH.DIR
/
00077_Script_aAnimator
< prev
next >
Wrap
Text File
|
1994-06-14
|
28KB
|
738 lines
--òò The central Animator script òòòòòòòòòòòòòòòòòòòòòòòòòòòòòòòòòòòòò
global gConstrainSprite
property theDelay,delayCounter,nGears,maxGears,gearList,nBalls,maxBalls,myBallList,¼
maxParts,nParts,nextPChannel,nextGChannel,myPartsList,myMotor,mySpeed,¼
initGearChannel,initBallChannel,initPartChannel, testList,¼
smGearID,lgGearID,bltGearID,pshGearID,teeID,chuteID,nSlopeID,pSlopeID
on birth me
-- EACH PART HAS AN ID. used for save / open to identify the part in the file
set lgGearID = 1
set smGearID = 2
set pshGearID = 3
set bltGearID = 4
set teeID = 5
set chuteID = 6
set nSlopeID = 7
set pSlopeID = 8
-- init the ball, gear, and part list and channel boundry vars
set nBalls = 0
set maxBalls = 1
set initBallChannel = 9
set nextBChannel = initBallChannel
set nGears = 0 -- holds the current gear count
set maxGears = 4 -- max number of gears, counting the Motor gear
set initGearChannel = 4 -- 1st gear channel,holds Motor gear, build
-- from here on down to max
set nextGChannel = initGearChannel -- next available channel for a gear part
set nParts = 0 -- holds the current parts count
set maxParts = 9 -- max number of parts, counting the vac chute
set initPartChannel = 11 -- 1st part channel,holds vac chute, build
-- from here on down to max
set nextPChannel = initPartChannel -- next available channel for a part
set mySpeed = 0 -- initial speed is 0, connects control to gear rotation
puppetSprite 27, TRUE -- holds the speed control device
-- create the list to hold gears
set gearList = [] -- empyt list at first, motor gear will be the first gear in list
-- Create a Motor Gear , birth a new offspring from the "aGear" script
-- Motor gear artwork starts at cast 591. 3 gears per animation, geartype = lgGearID
set myMotor = birth (script "aGear",nextGChannel,211,3,lgGearID)
mAddToGearList( me,myMotor) -- holds the list of gears for animation.
mSetEngaged ( myMotor,TRUE) -- gears that are engaged are powered = they turn.
-- Create a ball list and balls.
set myBallList = []
set theDelay = 8
set delayCounter = 8
-- build the parts list
set myPartsList = []
put mIncBallNumber (me) into thisPart
if objectp(thisPart) then
set theSprite = mGetSprite (thisPart )
put the width of sprite gConstrainSprite into theWidth
set theCenter = (the left of sprite gConstrainSprite) + theWidth/2
set the locV of sprite nBalls + initBallChannel =¼
(the top of sprite gConstrainSprite) + 50
set the locH of sprite nBalls + initBallChannel = theCenter + 108
end if
return me
end birth
--=================================================================
-- This handler takes a part number, calls the mNewPart handler
-- to get a new part and puts it on the stage relative to the mouseH.
-- If a part could not be created FALSE is returned. If the part
-- was created the this handler returns TRUE
on mCreatPart me, partNumber
set thisSprite = mNewPart (me,partNumber)
-- Test to see if the animator was able to create a new part
if thisSprite then
--put this part on the stage
set the locH of sprite thisSprite = the mouseH
set the locV of sprite thisSprite = 200
set the mouseUpScript to "snapToBoard"
return TRUE
else
return FALSE
end if
end mCreatPart
--=================================================================
-- This handler takes a part number (1 - 8 ) as a parameter and
-- births a new part based upon that number. If the part interacts
-- with the ball then the mAddToPartsList handler is called. If the
-- part is a gear the mAddToGearList handler is called. The channel
-- that holds the sprite is determined by calling mGetNextChannel or
-- mGetNextGearChannel handler. Then the handler returns the channel
-- number.
on mNewPart me, partNumber
set thisPart = 0
if partNumber = 8 then
-- build up sloped slide
set theChannel = mGetNextChannel ( me )
if theChannel <> 0 then
set thisPart = birth (script "aPChute" , theChannel,pSlopeID)
mAddToPartsList (me,thisPart)
end if
else
if partNumber = 7 then
-- build dwn sloped slide
set theChannel = mGetNextChannel ( me )
if theChannel <> 0 then
set thisPart = birth (script "aNChute" , theChannel,nSlopeID)
mAddToPartsList (me,thisPart)
end if
else
if partNumber = 6 then
--pusher gear
set theChannel = mGetNextGearChannel ( me )
if theChannel <> 0 then
set thisPart = birth (script "aGear" , theChannel,221,24,3 )
mAddToPartsList( me,thisPart)
mAddToGearList (me,thisPart)
end if
else
if partNumber = 5 then
-- build a slide Chute
set theChannel = mGetNextChannel (me)
if theChannel <> 0 then
set thisPart = birth (script "aChute" , theChannel,chuteID)
mAddToPartsList (me,thisPart)
end if
else
if partNumber = 4 then
-- build horz Belt
set theChannel = mGetNextGearChannel ( me )
if theChannel <> 0 then
set thisPart = birth (script "aGear" ,theChannel,181,1,4)
mAddToGearList (me,thisPart)
end if
else
if partNumber = 3 then
-- large gear
set theChannel = mGetNextGearChannel( me )
if theChannel <> 0 then
set thisPart = birth (script "aGear" ,theChannel,191,3,1)
mAddToGearList (me,thisPart)
end if
else
if partNumber = 2 then
-- small gear
set theChannel = mGetNextGearChannel (me )
if theChannel <> 0 then
set thisPart = birth (script "aGear" ,theChannel,201,3,2)
mAddToGearList (me,thisPart)
end if
else
if partNumber = 1 then
-- build a Tee Chute
set theChannel = mGetNextChannel( me )
if theChannel <> 0 then
set thisPart = birth (script "aTeeChute" , theChannel,teeID)
mAddToPartsList (me,thisPart)
else
set theChannel = 0
end if
end if
end if
end if
end if
end if
end if
end if
end if
return theChannel
end mNewPart
--=================================================================
-- Manages the channel allocation of parts sprite. Just fill
-- up the channels starting witn the initpartChannel up to
-- the initPartChannel + maxParts. If we are full we return
-- 0. Otherwise we return the channel.
on mGetNextChannel me
if nextPChannel > initPartChannel + maxParts then
return 0
else
set nextPChannel = nextPChannel + 1
return nextPChannel
end if
end mGetNextChannel
--=================================================================
-- Manages the channel allocation of gear sprite. Just fill
-- up the channels starting witn the initpartChannel up to
-- the initPartChannel + maxParts. If we are full we return
-- 0. Otherwise we return the channel.
on mGetNextGearChannel me
if nextGChannel >= initGearChannel + maxGears then
return 0
else
set nextGChannel = nextGChannel + 1
return nextGChannel
end if
end mGetNextGearChannel
--=================================================================
-- This handler manages the speed control. The mouse position
-- is determined relative to the general height of the sprite
-- and a cast (PICT) is selected for the sprite.
-- The delay property var is set to a value of 0 - 7.
on mSetSpeed me
put the mouseV into vertPos
-- each cast member in this animation has a different height,
-- so I have experimented and I've found the following numbers
-- yeild the best results for this control
set bottomRange = 290
set totalRange = 35
set delta = totalRange / 7
set rangeMark = (((vertPos - bottomRange) / delta))
set rangeMark = min(rangeMark,7)
if rangeMark < 0 then set rangeMark = 0
set newCast = (158 - rangeMark)
put the castNum of sprite 27 into currentCast
if currentCast > newCast then
set fDelta = -1
else
set fDelta = 1
end if
repeat while currentCast <> newCast
set currentCast = currentCast + fDelta
set the castNum of sprite 27 = currentCast
updateStage
end repeat
set mySpeed = rangeMark
set theDelay = mySpeed
set delayCounter = theDelay
end mSetSpeed
--=================================================================
-- This handler is easy to descripbe but is a bit complex in nature.
-- We take a sprite as theBase, and search the gear list to see
-- if we are touching any of the gears in the list. The base is assumed
-- to be engaged (powered) and we want to produce a list of
-- the gears that we are touching. We also wish to set the engaged property
-- var of the gears that the base is touching so that these gears are
-- also powered. Gears are touching if they intersect, and are at
-- the same locV or locH positions and the two gears do not over
-- lape by more then the pixel depth of the gear tooth depth.
-- Run the Simulation and place a gear on the peg board. Move it
-- to peg positions on the horizontal and vertial axis of the
-- motor gear and see when it is and is not engaged. This handler
-- is determining engagment.
on mSearchBase me,theBase , retList
-- find all gears that ar touching this base gear
-- and store the gear(s) in the retList
set retIndex = 1
setAt(retList,retIndex,0)
set gearCount = nGears -- this is set to the number of gears in the list
set nextGearCount = initGearChannel + 1 -- skip over motor gear
repeat while (gearCount > 1)
-- find a gear that touches the base gear (if any exits)
if not(gearCount = theBase) then
if (sprite (theBase + initGearChannel - 1) intersects ¼
(gearCount + initGearChannel - 1)) then
-- base gear is in contact with this gear
-- gear intersection must be on horz or vert axis to engage
put the locH of sprite (theBase + initGearChannel - 1) into baseHorz
put the locH of sprite (gearCount + initGearChannel - 1) into testHorz
put the locV of sprite (theBase + initGearChannel - 1) into baseVert
put the locV of sprite (gearCount + initGearChannel - 1) into testVert
set engagedState = FALSE
if (baseHorz = testHorz) then
-- one last test, do gears overlap more then the tooth depth
-- if yes then not engaged, else engaged. The belt is a special case
-- since it engages in a different maner from gear tooth engagement
if (baseVert > testVert) then
if (the top of sprite (theBase + initGearChannel - 1) + 20 ¼
> the bottom of sprite (gearCount + initGearChannel - 1)) then
set engagedState = TRUE
end if
else
if (the top of sprite (gearCount + initGearChannel - 1) + 20 ¼
> the bottom of sprite (theBase + initGearChannel - 1)) then
set engagedState = TRUE
end if
end if
else
if (baseVert = testVert) then
-- one last test, do gears overlap more then the tooth depth
-- if yes then not engaged, else engaged
if (baseHorz > testHorz) then
if (the left of sprite (theBase + initGearChannel - 1) + 20 ¼
> the right of sprite (gearCount + initGearChannel - 1)) then
set engagedState = TRUE
end if
else
if (the left of sprite (gearCount + initGearChannel - 1) + 20 ¼
> the right of sprite (theBase + initGearChannel - 1)) then
set engagedState = TRUE
end if
end if
end if
end if
-- test if one gear is a belt, special case for belts
put getAt(gearList,theBase) into baseGear
set baseDirection = mGetDirection (baseGear)
put getAt(gearList,gearCount) into NextTestGear
set tst1 = mGetID (baseGear)
set tst2 = mGetID (NextTestGear)
if ((tst1 = 4 and tst2 <> 4) or ¼
(tst1 <> 4 and tst2 = 4) ) then
set engagedState = TRUE
end if
if (engagedState) then
-- OK engage the two gears
put getAt(gearList,theBase) into baseGear
set baseDirection = mGetDirection (baseGear)
put getAt(gearList,gearCount) into NextTestGear
set testEngaged = mGetEngaged (NextTestGear)
if not(testEngaged) then
mSetDirection (NextTestGear ,not(baseDirection))
mSetEngaged (NextTestGear ,TRUE)
set baseAltState = mGetAltState( baseGear)
--set mGetID = baseType( baseGear )
--set gearType = mGetID ( NextTestGear)
mSetAltState (NextTestGear ,not(baseAltState)) --not
-- search sucessfull save the gear in the retList
setAt(retList,retIndex,gearCount)
set retIndex = retIndex + 1
setAt(retList,retIndex,0)
end if
end if
end if
end if
-- test the next gear
set gearCount = gearCount - 1
end repeat
end mSearchBase
--=================================================================
-- This handler is used to set the atributes of a gear offspring.
-- Since the atributes of all gears are interdependent, when one
-- of them changes they potentially all change. So This handler
-- clears the atributes of all gear offspring in the gear list
-- and then recalculates the new atributes for all gears.
-- This is a complex task. To make it simpler the mSearchBase handler
-- is used to automate the recursive task of searching the gear list.
--
on mSetAtributes me,theSprite
put getAt(gearList,1) into motorGear
mSetAltState (motorGear ,FALSE)
--- clear all gear engagements. (not the motor gear which is always engaged
set clearEngageCount = nGears
repeat while clearEngageCount > 1
put getAt(gearList,clearEngageCount) into nextGear
mSetEngaged (nextGear,FALSE)
set clearEngageCount = clearEngageCount - 1
end repeat
-- now find each engagement starting with the motor and working our way up
set retList1 = []
set retList2 = []
put retList1 into listOfBases
put retList2 into listOfNewBases
setAt(listOfNewBases,1,1)
repeat while (getAt(listOfNewBases,1))
-- generic loop to search, with a given base, the list of gears
put listOfBases into holdIt -- hold this list while I switch list names
put listOfNewBases into listOfBases
put holdIt into listOfNewBases
set testBase = TRUE
set index = 1
put count(listOfBases) into nBases
repeat while (testBase and index <= nBases)
put getAt(listOfBases,index) into testBase
if testBase then
mSearchBase (me,testBase,listOfNewBases)
set index = index + 1
end if
end repeat
end repeat
end mSetAtributes
--=================================================================
-- This part is only made once.
on mMakeVacChute me
-- firstly, build the vac Chute
set thisPart = birth ( script "aVacChute",22)
mAddToPartsList( me,thisPart)
end mMakeVacChute
--=================================================================
on mGetPartsList me
return myPartsList
end mGetPartsList
--=================================================================
on mSetPartsList me,theList
set myPartsList = theList
end mSetPartsList
--=================================================================
-- The handler manages the parts list. As we add parts to the
-- list we increment the nParts property var. If we reach the max
-- we no longer allow parts to be added to the list and the handler
-- returns FALSE. If a part is added to the list TRUE is returned.
on mAddToPartsList me,thisPart
if nParts <= maxParts then
if objectP(thisPart) then
set nParts = nParts + 1
setAt(myPartsList,nParts,thisPart)
return TRUE
else
return FALSE
end if
else
return FALSE
end if
end mAddToPartsList
--=================================================================
-- The handler manages the gear list. As we add gears to the
-- list we increment the nGears property var. If we reach the max
-- we no longer allow gears to be added to the list and the handler
-- returns FALSE. If a gear is added to the list TRUE is returned.
on mAddToGearList me,thisPart
if nGears <= maxGears then
if objectP (thisPart) then
set nGears = nGears + 1
setAt(gearList,nGears,thisPart)
return TRUE
else
return FALSE
end if
else
return FALSE
end if
end mAddToGearList
--=================================================================
-- The handler manages the ball list. As we add ball to the
-- list we increment the nGears property var. If we reach the max
-- we no longer allow balls to be added to the list and the handler
-- returns FALSE. If a ball is added to the list TRUE is returned.
-- This version only supports one ball at present. If we wanted to
-- we could extend the fucntion of the mDoBallResponse handler of the
-- part offspring to managed more then one ball. At this level and up
-- in the structure of MECH one or more balls are assumed. Therefore
-- only the part script handlers need to be upgraded.
on mIncBallNumber me
-- there is a fixed number of balls,deal with it
if nBalls < maxBalls then
set nBalls = nBalls + 1
set thisPart = birth (script "aBall" ,nBalls + initBallChannel,myPartsList)
setAt(myBallList,nBalls,thisPart)
return thisPart
else
return 0
end if
end mIncBallNumber
--=================================================================
-- This handler broadcasts the parts list to
-- the balls stored in the ball list. This is necessary
-- so that the balls can interact with the parts.
on mBroadCastParts me
set count = 1
set delayCounter = theDelay
repeat while count <= nBalls
put getAt(myBallList,count) into thisBall
mSetPartsToTest (thisBall, nParts)
set count = count + 1
end repeat
end mBroadCastParts
--=================================================================
-- This is the animation handler. The balls and gears will
-- each be culled from their lists and their animation
-- handlers will be called. The deley property var is used
-- to control the speed of the gear animation.
on stepFrame me
-- move the ball
set count = 1
repeat while count <= nBalls
put getAt(myBallList,count) into thisBall
mAnimateBall (thisBall)
set count = count + 1
end repeat
if delayCounter = theDelay then
set delayCounter = 0
set count = 1
-- do gears
repeat while count <= nGears
put getAt(gearList ,count) into thisGear
mAnimateGear (thisGear)
set count = count + 1
end repeat
else
set delayCounter = delayCounter + 1
end if
end stepFrame
--=================================================================
-- This will purge everything this scrip owns. Don't call unless
-- you want to start all over againg, vac chute, motor, and lists
-- all need to be recreated. This handler is used so that
-- the simulation can be stoped and restarted in Director without
-- doing a REWIND command.
on mClearActors me
mClearAllParts(me)
put getAt(myPartsList,nParts) into thisPart
set thisPart = 0
set myPartsList = 0
put getAt(gearList,nGears) into thisPart
set thisPart = 0
set gearList = 0
set myBallList = 0
end mClearActors
--=================================================================
-- bounce all the balls in the ball list
on mBounceBall me
-- bounce the ball
set count = 1
repeat while count <= nBalls
put getAt(myBallList,count) into thisBall
mBounceBall (thisBall)
set count = count + 1
end repeat
end mBounceBall
--=================================================================
-- This handler will code the current state of the MECH SIM into
-- a string. The string can be use to write to a file.
--
on mGetMechSim me
-- determine, code, and save the current state of the MechSim to a string ,
-- return that string make file a header
put "MECH SIM File"&RETURN into headerStr -- return char is the line break char
set index = nParts
set numP = nParts -- hold this for awhile
set partSpecStr = ""
repeat while index > 1 -- don't store the vac chute
put getAt(myPartsList,index) into thisPart
if objectP(thisPart) then
set thisSprite = mGetSprite (thisPart )
put the locH of sprite thisSprite into thisLocH
put the locV of sprite thisSprite into thisLocV
set thisID = mGetID (thisPart )
end if
if thisSprite > initPartChannel then
set partSpecStr = partSpecStr &thisID & "," & thisLocH & "," & thisLocV & RETURN
else
set numP = numP - 1
end if
set index = index - 1
end repeat
set nPartsStr = "Num of Parts ="&numP&RETURN
set retStr = headerStr&nPartsStr&partSpecStr
set index = nGears
set retStr = retStr&"Numb of Gears ="&nGears&RETURN
repeat while index > 0 -- don't need to store the alwasy present motor gear : jake
put getAt(gearList,index) into thisPart
if objectP(thisPart) then
set thisSprite = mGetSprite (thisPart)
put the locH of sprite thisSprite into thisLocH
put the locV of sprite thisSprite into thisLocV
set thisID = mGetID (thisPart)
end if
set retStr = retStr &thisID & "," & thisLocH & "," & thisLocV & RETURN
set index = index - 1
end repeat
return retStr
end mGetMechSim
--=================================================================
-- Used to clear the peg board when we open a file and restore a
-- saved MECH state. Also used when the user selects the clear
-- peg board command (see the peg board script).
on mClearAllParts me
-- clear current gears and parts, but not the Motor or Vac Chute
repeat while nParts > 1
put getAt(myPartsList,nParts) into thisPart
if objectP(thisPart) then
set thisSprite = mGetSprite(thisPart)
set thisPart = 0
set the constraint of sprite thisSprite = FALSE
set the locH of sprite (thisSprite) = 7000
set the locV of sprite (thisSprite) = 7000
end if
set nParts = nParts -1
end repeat
repeat while nGears > 1
put getAt(gearList,nGears) into thisPart
if objectP(thisPart) then
set thisSprite = mGetSprite(thisPart)
set the constraint of sprite thisSprite = FALSE
set thisPart = 0
set the locH of sprite ( thisSprite) = -1000
set the locV of sprite (thisSprite) = -1000
end if
set nGears = nGears -1
end repeat
set nextPChannel = initPartChannel
set nextGChannel = initGearChannel
end mClearAllParts
--=================================================================
-- Used to restore a save MECH SIM state to the peg board.
--
on mSetMechSim me
-- get file
put fileIO(mNew,"?read","txt") into myFile
if objectP(myFile) then
mClearAllParts (me)
-- strip the header off
put myFile(mReadLine) into headerStr
if (headerStr = "MECH SIM File"&RETURN) then
-- get general parts
readToStage me,myFile
-- get the gears
readToStage me,myFile
myFile(mDispose)
puppetTransition 23, 4, 0, 0
upDateStage -- needed to get Director to register the new parts on the stage so that
-- we can then call mSetAtributes. mSetAtributes is uses sprite locH and locV info
mSetAtributes( me,5)
-- we need to tell the balls
mBroadCastParts(me)
else
alert("Sorry This is not a MECH file")
end if
end if
end mSetMechSim
--=================================================================
-- This handler maps part IDs to part Numbers.
-- They are different for historical reasons only. They could
-- now be one and the same. To make this change, one would
-- make have to change the calls to mNewPart and the lookup
-- table in that handler.
on mPartIDToPartn me,theID
if theID = chuteID then return 5 -- chute cast
if theID = smGearID then return 2 -- small gear
if theID = lgGearID then return 3 -- big gear
if theID = bltGearID then return 4 -- belt
if theID = teeID then return 1 -- tee Chute
if theID = pshGearID then return 6 -- pusher
if theID = nSlopeID then return 7 -- dwn slope
if theID = pSlopeID then return 8 -- up slope
else return 1
end mPartIDToPartn
--=================================================================
-- This handler reads a stream of data, from a file
-- and converts it into an part number. With the part number
-- it can then create a part of that type. It then places the
-- part on the peg board using the coorindates also read
-- from the file.
on readToStage me,thisFile
-- get numb of parts
put thisFile(mReadChar) into myChar
put NumToChar(myChar) into myChar
repeat while myChar <> "="
put thisFile(mReadChar) into myChar
put NumToChar(myChar) into myChar
end repeat
put thisFile(mReadChar) into myChar
put NumToChar(myChar) into myChar
put "" into pnStr
repeat while myChar <> RETURN
set pnStr = pnStr&myChar
put thisFile(mReadChar) into myChar
put NumToChar(myChar) into myChar
end repeat
put thisFile(mReadChar) into myChar
put NumToChar(myChar) into myChar
put value(pnStr) into index
-- get the parts
set count = 1
repeat while count < index
-- get the ID , used as an ID for the type of part
put "" into pnStr
repeat while (myChar <> ",")
set pnStr = pnStr&myChar
put thisFile(mReadChar) into myChar
put NumToChar(myChar) into myChar
end repeat
put value(pnStr) into thisID
put thisFile(mReadChar) into myChar
put NumToChar(myChar) into myChar
-- get locH and locV
put "" into pnStr
repeat while (myChar <> ",")
set pnStr = pnStr&myChar
put thisFile(mReadChar) into myChar
put NumToChar(myChar) into myChar
end repeat
put value(pnStr) into thisLocH
put thisFile(mReadChar) into myChar
put NumToChar(myChar) into myChar
put "" into pnStr
repeat while (myChar <> RETURN)
set pnStr = pnStr&myChar
put thisFile(mReadChar) into myChar
put NumToChar(myChar) into myChar
end repeat
put value(pnStr) into thisLocV
put thisFile(mReadChar) into myChar
put NumToChar(myChar) into myChar
-- create the part
set partNum = mPartIDToPartn (me,thisID)
set thisSprite = mNewPart (me,partNum)
if thisSprite then
--set thisSprite = mGetSprite (thisPart)
set the locH of sprite thisSprite = thisLocH
set the locV of sprite thisSprite = thisLocV
end if
set count = count + 1
end repeat
end readToStage